#pragma once
/**
=====================================================================================
* Interface Class
*
* 1. Race/Class/Realm select:
*  -> Use GetListOfRealms, GetListOfClasses, GetListOfRaces
*      to get valid lists
*  -> Use SelectRealm, SelectClass, SelectRace
*    to select
*  -> Use Reset to start over
*
* 2. Base info
*  -> Use GetStats, GetStatsLevel
*    to get Stats or Stats at Level X
*
*
*
=====================================================================================
**/

#define ERR_NO_ERROR   0
#define ERR_CANT_OPEN_TABLE  1
#define ERR_ILLEGAL_REALM  2
#define ERR_ILLEGAL_VALUE  3
#define ERR_STYLE_NOT_FOUND  4
#define ERR_ILLEGAL_SPELLLINE 5
#define ERR_ILLEGAL_SPELL  6
#define ERR_ILLEGAL_CAT   7
#define ERR_ILLEGAL_CLASS  8
#define ERR_ILLEGAL_RA   9
#define ERR_ILLEGAL_RACE  10
#define ERR_ILLEGAL_STYLELINE 11
#define ERR_ILLEGAL_VERSION 12
#define ERR_ILLEGAL_ENT_SIZE 13

#define R_UNDEF     -1
#define R_ALBION    0
#define R_HIBERNIA  1
#define R_MIDGARD   2



//////////////////////////////////////////////////////////////////////////
enum SPELL_TYPE_IDS
{
    STI_BUFF_STR = 1,
    STI_BUFF_CON = 2,
    STI_BUFF_DEX = 3,
    STI_BUFF_STR_CON = 4,
    STI_BUFF_DEX_QUI = 5,
    STI_BUFF_ACUITY = 6,
    STI_BUFF_COMBAT_SPEED = 7,
    STI_BUFF_CELERITY = 8
};



// helper
typedef CArray <int,int> IntArray;
typedef std::map<int,std::string> std_name_map;


struct sqlite3;
struct sqlite3_stmt;



/**
* @class CDBInterfaceSQL
**/
class CDBInterfaceSQL
{
    public:
        CDBInterfaceSQL(void);
        ~CDBInterfaceSQL(void);

#ifdef ONLY_US_DB
        bool        Init(LPCTSTR language);
#else
        bool        Init(LPCTSTR language, bool old_version);
        bool        IsEuroDB()              { return mb_old_version; }
#endif

        bool        CreateMemoryCopy();
        CString     CurrentLanguage()       { return mstr_current_language;}
        bool        IsInitialized()         { return mp_db != NULL; }
        void        DeleteContents();



        /**
        * Reset()
        * unselect realm,class,race,.....
        **/
        void        Reset();

        // ----------------------------------------------------
        // REALM
        // ----------------------------------------------------
        /**
        * GetListOfRealms(StringArray& output);
        *
        * @return Stringlist of all Realms
        **/
        void        GetListOfRealms(CStringArray& output);

        /**
        * Selects a realm
        * all further calls will only respond to that realm
        **/
        void        SelectRealm(int id);

        /**
        * Returns selected Realm name
        **/
        CString     GetRealmName();
        CString     GetRealmName(int i);
        int         GetRealmID(const CString &);
        int         GetRealm();


        // ----------------------------------------------------
        // CLASSES
        // ----------------------------------------------------
        /**
        * GetListOfClasses(StringArray& output);
        *
        * @return Stringlist of all Classes
        * if a realm is selected -> only classes of that realm
        **/
        void        GetListOfClasses(IntArray& output);

        /**
        * Selects a Class
        * all further calls will only respond to that class
        *   ( realm will change too)
        **/
        void        SelectClass(int id);

        int         GetClassID();
        int         GetClassID(const CString& str_class);


        /**
        * Returns selected Class name
        **/
        mstring     GetClassName();
        CString     GetClassName(int id);


        /**
        *   Returns TRUE if class is for female chars only
        **/
        bool        IsClassFemaleOnly();

        /**
        * Returns TRUE if class is a list-caster (acu-buff able)
        **/
        bool        IsClassListCaster();


        /**
        * Returns selected Class Hitpoints-calculation values
        **/
        void        GetClassesHPModifier(int &basehps, double& confactor);
        /**
        * Returns selected Class WeaponF-calculation values
        **/
        void        GetClassesWFModifier(int &basewfs, double& conwf, int &basewfs_b, double& wffactor_b);


        // ----------------------------------------------------
        // RACES
        // ----------------------------------------------------
        /**
        * GetListOfRaces(StringArray& output);
        *
        * @return Stringlist of all Races valid for selected class
        **/
        void        GetListOfRaces(IntArray& output);

        void        SelectRace(int id);
        int         GetRaceID();

        /**
        * Returns selected Race name
        **/
        CString     GetRaceName();
        CString     GetRaceName(int id);

        /**
        *
        **/
        void        GetRaceResis(CStringArray& names,IntArray& perc);

        // ----------------------------------------------------
        // STATS
        // ----------------------------------------------------
        void    GetStats(int stats[8]);
        void    GetStatsLevel(int stats[8], float level);
        int     GetSkillPoints(float level);
        void    GetStatsPrimary(int pri[4]); // 0-pri,1-sec,2-ter,3-magie



        // ----------------------------------------------------
        // Styles
        // ----------------------------------------------------
        void    GetListOfStyleLines(CStringArray& output);

        void    SelectStyleLine(const CString& styleline);
        CString GetStyleLineName();

        void    GetListOfStyles(CStringArray* names, IntArray* level=NULL, IntArray* ids=NULL);

__declspec(deprecated("** SelectStyle is deprecated. Use SelectStyleID(int) instead **"))
        void    SelectStyle(const CString& style);
        void    SelectStyleID(int style_id);

        void    GetStyleDescription(CStringArray& name, CStringArray& val, int style =-1);

        /**
        *   \return 0-none; 1-front; 2-back; 3-side; 4-evade; 5-block; 6-parry; bit 8 -> Stealthed
        **/
        int     GetStylePrePos();

        /**
        *  \return name of pre-style or ""
        **/
        CString GetStylePreStyle();
        int     GetStylePreStyleID();

        CString GetStyleDescriptionText();
        CString GetStyleDetailtext(int id);

        bool    IsStyleLineAutotrain();

        int     GetStyleID();
        int     GetStyleLineID();
        int     FindStyleLine(const char*);

        CString GetStyleLineNameEx(int ext);



        // ----------------------------------------------------
        // Spells
        // ----------------------------------------------------

        /**
        *   List of all BASE spell-lines
        **/
        void            GetListOfSpellLines(CStringArray& output);  // just base

        /**
        *   List of all spell-lines (Base + Spec)
        * Always Base followed by Spec  (it's possible that on of it is empty or atleast has no categories)
        **/
        void            GetListOfAllSpellLines(CStringArray& output); // base and spec

        CString         GetSkillName();
        CString         GetSpellLineNameBase();
        CString         GetSpellLineNameSpec();

        /**
        * Get a list of all spell-categories
        **/
        void            GetListOfSpellCatsBase(CStringArray& names);
        void            GetListOfSpellCatsSpec(CStringArray& names);
        int             GetSpellCatDisplayFlag();

        /**
        * Get a list of all spell-categories including internal types
        * Note: only cats with a ID will be returned
        **/
        void            GetListOfSpellCatsBaseAndID(CStringArray& names, IntArray& types);
        void            GetListOfSpellCatsSpecAndID(CStringArray& names, IntArray& types);

        bool            HasBaseSpells();
        bool            HasSpecSpells();

        void            SelectSpellLine(const CString& spelllinename);
        void            SelectSpellCatBase(const CString& spellname);
        void            SelectSpellCatSpec(const CString& spellname);
__declspec(deprecated("** SelectSpell is deprecated. Use SelectSpellID(int) instead **"))
        void            SelectSpell(const CString& spell, int level);
        void            SelectSpellID(int style_id);


        void            GetListOfSpells(CStringArray* names, IntArray* level = NULL, IntArray* ids = NULL);

        void            GetSpellDescription(CStringArray& name, CStringArray& val);
        CString         GetSpellDescriptionEffect();
        CString         GetSpellDescriptionText();
        CString         GetHighestSpellEffect(int level);
        CString         GetSpellDamType();

        bool            IsSpellLineAutotrain();

        int             FindSpellLine(const CString& name);
        CString         GetSpellLineNameEx(int ext);

        bool            IsFakeSpell(int id);


        // ----------------------------------------------------
        // RAs
        // ----------------------------------------------------
        void            GetListOfRAs(CStringArray& output, IntArray&type);

        void            SelectRA(const CString&);

        CString         GetRAName(int id);

        int             GetRAReUseTime();
        void            GetRALevels(int l[5]);
        void            GetRARequirement(CString& name, int& level);
        CString         GetRADescription();
        int             FindRA(const CString&, int nclass);


        // ----------------------------------------------------
        // RAs NewFrontiers
        // ----------------------------------------------------
        void            GetListOfRANF(IntArray& output);

        CString         GetRANFName(int id);
        CString         GetRANFName();

        void            SelectRANF(int id);
        int             GetRANFCost(int level, bool fake_points=false);

        void            GetRAInfoNF(std::string& shortname, std::string& reuse, int& ratype, int& type);
        void            GetRALevelsNF(std::string l[9]);

        CString         GetRADescriptionNF();
        bool            IsFakeRANF(int id);

        int             FindRANF(const CString&, int nclass);

        int		        GetRANFStatModif(int id, int level);

        /** @param realmrank 1-130 **/
        CString         GetRRName(int realmrank);
        unsigned        GetRR_RPs(int realmrank);


        // ----------------------------------------------------
        // Abilities
        // ----------------------------------------------------
        /**
         * @param name will recieve the names
         * @param level will recieve the level when the skill is available
         * @param type: 
                1   Base  (skillable)   + 16* (1="Strength";2="Dexerity";3="Str + Dex";4="Bow (dex)";0="none") 
                2   Spec  (skillable)
                3   Armor
                4   Shields
                5   Banner
                6   Style
                7   Style (NOT skillable) + (see 1)
         */
        void            GetListOfAbilities(CStringArray& name, IntArray& level,IntArray& type);
        CString         GetAbilityDesc(const CString&, bool style_only = false);


        // ----------------------------------------------------
        // MasterLevels
        // ----------------------------------------------------
        CString         GetMasterTrack(int path);
        void            SelectMasterTrack(const CString&);
        void            GetMasterLevels(CStringArray& results);
        void            GetMasterLevelInfo(int level, CString&target, int& timer);
        CString         GetMasterDescription(int level);

        void            GetMasterQuests(int level, CStringArray& names, IntArray& type);


        // ----------------------------------------------------
        // Champion-Levels
        // ----------------------------------------------------
        void            GetListOfChampTrainers(CStringArray&, IntArray&);
        void            GetListOfChampSpells(const CString&,int nr,IntArray&);
        void            GetChampSpell(int id, CString&,CString&,CStringArray&,int&);


        // ----------------------------------------------------
        // Edit stuff
        // ----------------------------------------------------
        void            EditAddRA(int realm, int type,const char* name_en, const char* name_de=NULL, const char*name_fr=NULL,  
                                  const char* short_desc=NULL, bool active = false, 
                                  const char* desc_en=NULL, const char* desc_de=NULL, const char* desc_fr=NULL, 
                                  const char** levels=NULL, int reuse=0);
        void            EditAddRA(const char* class_id, int type,const char* name, const char* short_desc=NULL, bool active = false, const char* desc=NULL, const char** levels=NULL, const char* reuse=NULL);
        INT_PTR         EditAddSpellLine(const TCHAR* skill,const TCHAR* base,const TCHAR* spec);
        void            EditAddClassLine(int realm, INT_PTR id);
        void            EditAddClassLine(const TCHAR* class_id, INT_PTR id);
        int             EditAddSpellCat(INT_PTR spellline_id, bool base, const TCHAR*name, const TCHAR* desc);
        void            EditAddSpell(INT_PTR spell_cat_id, const TCHAR* name, int level,const TCHAR* target,const TCHAR* times,const TCHAR* range,const TCHAR* costs,const TCHAR* dam,const TCHAR* damtype);


        // ----------------------------------------------------
        // Import/Export stuff
        // ----------------------------------------------------
        mstring     MoraGetClassName();
        CString     MoraGetRaceName();


        // ----------------------------------------------------
        // Debug stuff
        // ----------------------------------------------------
        void        ErrorOut(int error_code, CString text);
        bool        DebugCheckIfSpecable(int class_id, const CString& str_line);
        CString     GetDBState();


    protected:

        // ----------------------------------------------------
        // SQL Helper
        // ----------------------------------------------------
        sqlite3_stmt*   sql_prepare(const char*,...);
        CString         sql_table_field(const CString& table, const CString& field);
        CString         sql_table_field_no_tab(const CString& table, const CString& field);
        const char*     sql_table_langEN_DE();
        const char*     sql_table_langEN_DE_FR();
        const char*     langEN_DE_FR();
        CString         sqlite3_escape_string(const CString& input);

        bool            sqlite3_column_bool(sqlite3_stmt*,int);

        bool            sql_CheckForError(int res, int expected = 0 /*SQLITE_OK*/);

    public:
        bool            sql_execute(const char*,...);


    protected:


        sqlite3*    mp_db;

        CString     mstr_current_language;

#ifndef ONLY_US_DB
        bool        mb_old_version;
#endif

        int         mn_selected_realm;
        int         mn_selected_race;
        int         mn_selected_styleline;
        int         mn_selected_style;
        int         mn_selected_spellline;
        int         mn_selected_spellcat;
        int         mn_selected_spell;
        int         mn_selected_ra;
        int         mn_selected_raNF;
        int         mn_selected_mastertrack;

        bool        mb_suspend_sql_error;


        // DB-Cache
        class db_class
        {
            public:
                int     id;
                int     realm;
                mstring name;
                mstring mora_ID;
                bool    IsListCaster;
                bool    IsFemaleOnly;
                int     HP_base;
                double  HP_confactor;
                int     WF_base;
                double  WF_factor;
                int     WF_base_bow;
                double  WF_factor_bow;
        };
        /** @todo move these into classes (requires db-class singleton)**/
        bool    db_read_class(int i);


        db_class    m_class;

};


extern CDBInterfaceSQL gdbinterface;

